{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Noise\n",
    "\n",
    "For simulation, it is useful to have `Gate` objects that enact noisy quantum evolution.\n",
    "\n",
    "Cirq supports modeling noise via *operator sum* representations of\n",
    "noise (these evolutions are also known as quantum operations, quantum\n",
    "dynamical maps, or superoperators).  \n",
    "\n",
    "This formalism models evolution of the\n",
    "density matrix via:\n",
    "\n",
    "$$\\rho \\rightarrow \\sum_k A_k \\rho A_k^\\dagger$$\n",
    "\n",
    "Where A<sub>k</sub> are *Krauss* operators. These operators are not\n",
    "necessarily unitary and must satisfy the trace-preserving property:\n",
    "\n",
    "$$\\sum_k A_k^\\dagger A_k = I$$\n",
    "\n",
    "As a noisy channel, Krauss operators are not unique. For more details of these operators, see [John Preskill's notes](http://www.theory.caltech.edu/people/preskill/ph219/chap3_15.pdf).\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Magic methods\n",
    "\n",
    "A `Gate` can represent an operator sum representation by supporting the\n",
    "`channel` protocol.  Alternatively, for channels that represent probabilistic\n",
    "mixtures of unitaries, one can implement the `mixture` protocol."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### cirq.channel and def _channel_\n",
    "\n",
    "To represent an operator sum evolution, a `Gate` should implement the\n",
    "`SupportsChannel` protocol. To do this, the `Gate` should implement the\n",
    "`_channel_(self) -> Sequence[np.ndarray]:` method. \n",
    "\n",
    "This method should return the sequence of `numpy` matrices corresponding to the Krauss operators. The basis in which this matrix is expressed is always implicit with respect to the object being called. \n",
    "\n",
    "For example, in `GateOperations`, these matrices must be ordered with respect to the list of qubits that the channel is applied to. The qubit-to-amplitude order mapping matches the ordering of `numpy.kron(A, B)`, where `A` is a qubit earlier in the list than the qubit `B`.\n",
    "\n",
    "If one has defined `_channel_`, then that `Gate` and any `GateOperation`\n",
    "that uses that gate can be used as an argument to `cirq.channel` and\n",
    "`cirq.channel` will return this sequence of matrices.\n",
    "\n",
    "Besides objects that support `_channel_`, `cirq.channel` will also fall\n",
    "back to other objects that can be interpreted as channels. For example, if a channel is a probabilistic mixture of unitary gates (see below), then `cirq.channel` will fall back to seeing if the object supports `_mixture_`. If `_mixture_` is not supported, then `cirq.channel` checks to see if `_unitary_` is supported.\n",
    "\n",
    "In addition to supporting `_channel_`, objects that are channels should also implement `_has_channel_(self) -> bool` to return `True`. This method is used to determine whether an object has a `_channel_` or not without having to do the potentially expensive creation of the matrices for the channel."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### cirq.mixture and def _mixture_\n",
    "\n",
    "Some channels can be interpreted as probabilistically selecting between\n",
    "different unitary evolutions:\n",
    "\n",
    "$$\\rho \\rightarrow \\sum_k p_k U_k \\rho U_k^\\dagger {\\rm ~where~} \\sum_k p_k =1 {\\rm ~and~ U_k U_k^\\dagger= I}$$\n",
    "\n",
    "In this case, it is possible to perform **Monte Carlo simulations** of these gates using a wave function based simulator (and not a density matrix based simulator).  \n",
    "\n",
    "Instead of implementing the `SupportsChannel` protocol, one should implement the `SupportsMixture` protocol. To do this, one should implement the `_mixture_(self) -> Sequence[Tuple[float, np.ndarray]]` protocol.  This returns a sequence of tuples. \n",
    "\n",
    "The first element of each tuple is the probability of the unitary, and the second element is the unitary. Like the `_channel_` method described above, the basis for these matrices is implicit with respect to the object being called. One should also make `_has_mixture_` return `True` to indicate to callers that the object supports the mixture protocol. \n",
    "\n",
    "If one wants to get the mixture channel directly, one can call `cirq.mixture`.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Common Channels\n",
    "\n",
    "Cirq supports many commonly used quantum channels out of the box, see\n",
    "[`ops/common_channels.py`](https://github.com/quantumlib/Cirq/blob/master/cirq/ops/common_channels.py).\n",
    "\n",
    "#### AsymmetricDepolarizingChannel, DepolarizingChannel, BitFlipChannel, and PhaseFlipChannel\n",
    "\n",
    "The asymmetric depolarizing channel represents probabilistically selecting\n",
    "one of three Pauli gates to apply or doing nothing to the state. This is\n",
    "implemented via a `_mixture_` method so that a Monte Carlo simulation with a\n",
    "wave function simulator can be used.\n",
    "\n",
    "This channel implements the evolution:\n",
    "\n",
    "$$\n",
    "\\rho \\rightarrow (1-p_x-p_y-p_z) \\rho + p_x X \\rho X + p_y Y \\rho Y + p_z Z \\rho Z\n",
    "$$\n",
    "\n",
    "Here p<sub>x</sub> is the probability that the X Pauli gate is applied and\n",
    "no other gate is applied, and similarly for p<sub>y</sub> and p<sub>z</sub>.\n",
    "\n",
    "A particular case of the asymmetric depolarizing channel is the case when each of the different Paulis occur with the same probability. This is\n",
    "encapsulated in the `DepolarizingChannel` gate, which takes a probability `p`\n",
    "such that each Pauli gate occurs with probability `p/3`.\n",
    "\n",
    "To construct channels, useful helpers are provided `cirq.asymmetric_depolarize`\n",
    "and `cirq.depolarize`.\n",
    "\n",
    "Another common case is when only a Pauli X (bit flip) can occur, or\n",
    "when only a Pauli Y (phase flip) can occur. These correspond to\n",
    "`BitFlipChannel` and `PhaseFlipChannel` with helpers `cirq.bit_flip` and\n",
    "`cirq.phase_flip`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### GeneralizedAmplitudeDampingChannel and AmplitudeDampingChannel\n",
    "\n",
    "The generalized amplitude damping channel models the effect of energy\n",
    "dissipation to a surrounding environment as well as dephasing that\n",
    "does not exchange energy. The amplitude damping channel only models dissipation of energy to a surrounding environment. \n",
    "\n",
    "Cirq has implementations of both of these channels. The generalized amplitude damping channel corresponds to:\n",
    "\n",
    "$$\n",
    "\\begin{aligned}\n",
    "\\rho \\rightarrow& \\sum_{k=0}^3 M_k \\rho M_k \\newline\n",
    "M_0 =& \\sqrt{p} \\begin{bmatrix} 1 & 0  \\cr 0 & \\sqrt{1 - \\gamma} \\end{bmatrix} \\newline\n",
    "M_1 =& \\sqrt{p} \\begin{bmatrix} 0 & \\sqrt{\\gamma} \\cr 0 & 0 \\end{bmatrix} \\newline\n",
    "M_2 =& \\sqrt{1-p} \\begin{bmatrix} \\sqrt{1-\\gamma} & 0 \\cr 0 & 1 \\\\ \\end{bmatrix} \\newline\n",
    "M_3 =& \\sqrt{1-p} \\begin{bmatrix} 0 & 0 \\cr \\sqrt{\\gamma} & 0 \\end{bmatrix}\n",
    "\\end{aligned}\n",
    "$$\n",
    "\n",
    "Where &#947; is the probability of the interaction being dissipative, and\n",
    "`p` is the probability that the qubit and environment exchange energy. The amplitude damping channel corresponds to `p=1`.\n",
    "\n",
    "Cirq provides the helpers `cirq.generalized_amplitude_damp` and\n",
    "`cirq.amplitude_damp` to construct these noisy gates."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
